/*
 * Object   : MySimMgr
 * Type     : UI
 *
 * Narrator : Kamran H. Khan 
 * Email    : KAMRANHK@gmail.com
 * 
 * Copyleft : Attribution - CreativeCommons http://creativecommons.org/licenses/by-nc/3.0/
 *            This software is provided 'as-is', without any express or implied warranty.
 *            In no event will the author(s) be held liable for any damages arising from
 *            the use of this software.
 * 
 *            Permission is granted to anyone to use this software for any purpose,
 *            including commercial applications, and to alter it and redistribute it
 *            freely, subject to the following restrictions:
 * 
 *            1. The origin of this software must not be misrepresented; you must not
 *            claim that you wrote the original software. If you use this software
 *            in a product, an acknowledgment in the product documentation would be
 *            appreciated but is not required.
 * 
 *            2. Altered source versions must be plainly marked as such, and must not
 *            be misrepresented as being the original software.
 * 
 *            3. This notice may not be removed or altered from any source distribution.
 * 
 * Description: 
 * Provides the user interface, and handles network/translation modules
 * 
 * Revision History:
 * 
 * Date(MMM/dd/yy)      Owner           Description
 * ----------------------------------------------------------------------------------------------------------------------------------------------
 * Oct/24/08            Kamran H. Khan  Added skeleton code
 * Oct/25/08            Kamran H. Khan  Added more methods
 *  
 * 
 * 
 * 
*/


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Xml;
using System.IO;
using Maxima.Networker;
using Maxima.Common;

namespace Maxima.MySimMgr
{
    public partial class UCtlMySimMgr : UserControl
    {
        //string strFilenameXsd = "../../MySimulator.xsd"; //Schema for validation
        string strFilenameXml = "MySimulations.xml";

        private CSimHandler m_mySim;

        //Initialize NetMgr objects
        private CNetMgr m_theClient; //Client object from NetMgr
        private CNetMgr m_theServer; //Server, listens to clients'


        /// <summary>
        /// Initializes a new instance of the <see cref="UCtlMySimViewer"/> class.
        /// </summary>
        public UCtlMySimMgr()
        {
            InitializeComponent();
            txtXmlFilename.Text = strFilenameXml; //default xml file name

            m_mySim = new CSimHandler();

        }

        /// <summary>
        /// Reloads the simulations.
        /// </summary>
        public void ReloadSimulations()
        {
            if (File.Exists(txtXmlFilename.Text))
            {
                this.cbxSimulations.DataSource = m_mySim.LoadAllSimulations(txtXmlFilename.Text);
            }
            else
            {
                Log("Please provide a valid configuration file");
                BrowseForConfigFile();
            }
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the cbxSimulations control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void cbxSimulations_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbxSimulations.SelectedIndex > -1)
            {
                m_mySim.SimulatorName = cbxSimulations.SelectedItem.ToString();
                cbxTransactions.DataSource = m_mySim.LoadAllTransactions(cbxSimulations.SelectedItem.ToString());

                lbtIP.Text = m_mySim.IP;
                lbtPort.Text = m_mySim.Port.ToString();
                lbtRunas.Text = m_mySim.IsServer ? "Server" : "Client";
            }
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the cbxTransactions control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void cbxTransactions_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbxTransactions.SelectedIndex < 0)
                return;

            m_mySim.LoadTransactionByName(cbxTransactions.SelectedItem.ToString());

            lbtTransactionCode.Text = m_mySim.TransactionCode;

            lbxMessages.Items.Clear();
            lbxMessages.Items.Add(m_mySim.Header);
            string strValue = m_mySim.RequestMsg.Replace("\0", "?");
            lbxMessages.Items.Add(strValue);
            strValue = m_mySim.ResponseMsg.Replace("\0", "?");
            lbxMessages.Items.Add(strValue);
        }



        /// <summary>
        /// Handles the SelectedIndexChanged event of the lbxMessages control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void lbxMessages_SelectedIndexChanged(object sender, EventArgs e)
        {
            string strData = string.Empty;
            if (lbxMessages.SelectedIndex > -1 && lbxMessages.SelectedIndex < lbxMessages.Items.Count)
            {
                switch (lbxMessages.SelectedIndex)
                {
                    case 1://Request
                        strData = lbxMessages.Items[1].ToString();
                        break;
                    case 2: //Response
                        strData = lbxMessages.Items[2].ToString();
                        break;
                    default:
                        lbxMessages.SelectedIndex = 1;
                        strData = lbxMessages.Items[1].ToString();
                        break;
                }

                txtMsg.Text = strData;

            }
        }

        /// <summary>
        /// Handles the Click event of the btnBrowse control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnBrowse_Click(object sender, EventArgs e)
        {
            BrowseForConfigFile();
        }

        /// <summary>
        /// Browses for config file.
        /// </summary>
        private void BrowseForConfigFile()
        {
            OpenFileDialog theDlg = new OpenFileDialog();
            theDlg.Filter = "MySim9 Simulators (*.xml) | *.xml";

            if (theDlg.ShowDialog() == DialogResult.OK)
            {
                if (theDlg.FileName.ToLower().EndsWith(".xml"))
                {
                    txtXmlFilename.Text = theDlg.FileName;
                    ReloadSimulations();
                }
                else
                {
                    Log("Invalid file, please provide a valid xml file.");
                }
            }
        }

        /// <summary>
        /// Handles the LinkClicked event of the lnkGenerate control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void lnkGenerate_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            string strTempFilePath = m_mySim.GenerateSampleXml();
            Log("Sample xml file " + strTempFilePath + " generated in local folder. Please select and edit the xml file.");

        }

        /// <summary>
        /// Logs the specified STR MSG.
        /// </summary>
        /// <param name="strMsg">The STR MSG.</param>
        private void Log(string strMsg)
        {
            MaintainLog(strMsg);
            MessageBox.Show(strMsg, System.Diagnostics.EventLogEntryType.Information.ToString(), MessageBoxButtons.OK, MessageBoxIcon.Information);

        }

        private void MaintainLog(string strMsg)
        {
            if (!chkLogFile.Checked && !lnkMaintainLogFile.Enabled)
                return;
            else
            {
                CLogger.GetInstance().Debug(this.GetType().Name, System.Reflection.Emit.MethodBuilder.GetCurrentMethod().Name, DateTime.Now.ToString("yy/MM/dd HH:mm:ss.fff") + "\t| " + strMsg, System.Diagnostics.EventLogEntryType.Information);
            }
        }

        /// <summary>
        /// Handles the LinkClicked event of the lnkEdit control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void lnkEdit_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("notepad.exe", txtXmlFilename.Text);
        }

        /// <summary>
        /// Handles the LinkClicked event of the lnkReload control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.LinkLabelLinkClickedEventArgs"/> instance containing the event data.</param>
        private void lnkReload_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ReloadSimulations();
        }

        /// <summary>
        /// Handles the Click event of the btnStart control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (cbxSimulations.SelectedIndex < 0)
            {
                Log("Click reload, and then start");
                return;
            }

            if (btnStart.Text.Equals("Start"))
            {
                Start();
                btnStart.Text = "Stop";
                btnBrowse.Enabled = false;
                cbxSimulations.Enabled = false;
            }
            else
            {
                Stop();
                btnStart.Text = "Start";
                btnBrowse.Enabled = true;
                cbxSimulations.Enabled = true;
            }

        }

        /// <summary>
        /// Stops this instance.
        /// </summary>
        private void Stop()
        {
            if (m_mySim.IsServer)
            {
                StopServer();
            }
            else
            {
                StopClient();
            }

        }

        /// <summary>
        /// Stops the client.
        /// </summary>
        private void StopClient()
        {
            m_theClient.Stop();
        }

        /// <summary>
        /// Stops the server.
        /// </summary>
        private void StopServer()
        {
            m_theServer.Stop();
        }

        /// <summary>
        /// Starts this instance.
        /// </summary>
        private void Start()
        {
            if (m_mySim.IsServer)
            {
                StartServer();
            }
            else
            {
                StartClient();
            }
        }

        /// <summary>
        /// Starts the client.
        /// </summary>
        private void StartClient()
        {
            //Instantiate with the IP/Port and connection type (Server/client)
            m_theClient = new CNetMgr(lbtIP.Text, //IP address to connect to
                                      Convert.ToInt32(lbtPort.Text), //Server port
                                      false); //False = not server

            //Add event to know about the new messages being arrived
            m_theClient.OnStatusChange += new CNetMgr.StatusChangeEventHandler(m_theClient_OnStatusChange);

            //Start the client, lets connect.
            m_theClient.Start();
        }

        /// <summary>
        /// M_thes the client_ on status change.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <param name="bIsServer">if set to <c>true</c> [b is server].</param>
        void m_theClient_OnStatusChange(string strData, bool bIsServer)
        {

            if (IsConnected())
            {
                if (strData.StartsWith("MSG["))
                {
                    bool bShouldRespond = m_mySim.TranslateThisMessage(strData);
                    if (bShouldRespond)
                    {
                        Send(m_mySim.ResponseMsg);
                        Log(m_mySim.ResponseMsg, bIsServer);
                    }
                }
                else
                    Log(strData, bIsServer);
            }
            else
            {
                Log(strData, bIsServer);
            }
        }

        /// <summary>
        /// Determines whether this instance is connected.
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if this instance is connected; otherwise, <c>false</c>.
        /// </returns>
        private bool IsConnected()
        {
            bool bStatus = false;

            if (m_theClient != null)
            {
                if (m_theClient.IsConnected(false))
                {
                    bStatus = true;
                }
            }
            else if (m_theServer != null)
            {
                if (m_theServer.IsConnected(true))
                {
                    bStatus = true;
                }
            }
            else
                bStatus = false;

            return bStatus;
        }

        /// <summary>
        /// Starts the server.
        /// </summary>
        private void StartServer()
        {
            //Define the server settings, constructor
            m_theServer = new CNetMgr(lbtIP.Text, //IP address of this server, usually, localhost (this machine)
                                      Convert.ToInt32(lbtPort.Text), //Port to listen at
                                      true);//true = server

            //Register to listen for the events of new messages arrived
            m_theServer.OnStatusChange += new CNetMgr.StatusChangeEventHandler(m_theServer_OnStatusChange);

            //Start the server, start listening
            m_theServer.Start();
        }

        /// <summary>
        /// M_thes the server_ on status change.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <param name="bIsServer">if set to <c>true</c> [b is server].</param>
        void m_theServer_OnStatusChange(string strData, bool bIsServer)
        {
            if (IsConnected())
            {
                if (strData.StartsWith("MSG["))
                {
                    bool bShouldRespond = m_mySim.TranslateThisMessage(strData);
                    if (bShouldRespond)
                    {
                        int nIndexStart = strData.IndexOf("[");
                        int nIndexEnd = strData.IndexOf("]") - 1 - 1;
                        string strMsg = strData.Substring(nIndexStart, nIndexEnd);
                        strMsg = strMsg + m_mySim.ResponseMsg;
                        Send(strMsg);
                        Log(m_mySim.ResponseMsg, bIsServer);
                    }
                }
                Log(strData, bIsServer);
            }
            else
                Log(strData, bIsServer);
        }

        /// <summary>
        /// Logs the specified STR data.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        /// <param name="bIsServer">if set to <c>true</c> [b is server].</param>
        private void Log(string strData, bool bIsServer)
        {
            //int nIndex = strData.LastIndexOf("]");
            //try
            //{
            //    if (strData[nIndex + 1].ToString() == "\0")
            //        strData[nIndex + 1].ToString().Replace("\0", "?");
            //}
            //catch (Exception exc) { }

            string strValue = strData.Replace("\0", "?");

            if (strData.Contains("RX"))
            {
                ;
            }

            if (bIsServer)
                txtStatus.Text += Environment.NewLine + strData; //"SVR:>" +
            else
                txtStatus.Text += Environment.NewLine + strData; //"CLNT:>" + 

            txtStatus.SelectionStart = txtStatus.TextLength;
            txtStatus.ScrollToCaret();

            MaintainLog(strData);
        }

        /// <summary>
        /// Handles the Click event of the btnSend control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            Send(txtMsg.Text);
        }

        /// <summary>
        /// Sends the specified STR data.
        /// </summary>
        /// <param name="strData">The STR data.</param>
        private void Send(string strData)
        {
            if (IsConnected())
            {
                if (m_mySim.IsServer)
                    m_theServer.Send(strData);
                else
                    m_theClient.Send(strData);
            }
        }

        private void lnkHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            string strHelpFilePath = Application.ExecutablePath.ToString().ToLower();
            strHelpFilePath = strHelpFilePath.Replace("mysim9.exe", "mysim.mht");
            if (File.Exists(strHelpFilePath))
                System.Diagnostics.Process.Start("IEXPLORE.exe", strHelpFilePath);
            else
                Log("Help file not found. Please provide mysim.mht in the executable directory");

        }

        private void chkLogFile_CheckedChanged(object sender, EventArgs e)
        {
            MaintainLog("Log file turned: " + ((chkLogFile.Checked) ? "[On]" : "[Off]"));
            lnkMaintainLogFile.Enabled = chkLogFile.Checked;


        }

        private void lnkMaintainLogFile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            string strLogFilePath = Application.ExecutablePath.ToString().ToLower();
            string strLogFilename = "MySim9-Log-" + DateTime.Now.Day.ToString().PadLeft(2, '0') + DateTime.Now.Month.ToString().PadLeft(2, '0') + ".log";
            strLogFilePath = strLogFilePath.Replace("mysim9.exe", strLogFilename);

            if (File.Exists(strLogFilePath))
                System.Diagnostics.Process.Start("notepad.exe", strLogFilePath);
            else
                Log("Log file not found.");
        }

        private void lnkMaximaLabs_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("IEXPLORE.exe", lnkMaximaLabs.Text);
        }


    }
}
